using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using TouchSmart.Animations;
using TouchSmart.Drawing;
using TouchSmart.Gestures;
using TouchSmart.Widgets;

namespace TouchSmart
{
    public class Host : Control
    {
        private BackBuffer _backBuffer;
        private EventDriver _eventDriver;
        private readonly List<Widget> _widgets;
        

        public Host()
        {
            this._widgets = new List<Widget>();
        }

        public void Initialize()
        {
            this._backBuffer = new BackBuffer(this);
            this._eventDriver = new EventDriver(this);
            this._eventDriver.Click += ClickHandler;
            this._eventDriver.Movement += MovementHandler;
            this._eventDriver.MouseDown += MouseDownHandler;
            this._eventDriver.MouseUp += MouseUpHandler;
            this._eventDriver.Slide += SlideHandler;

            Locator.Register<IAnimator>(new Animator(this));
            Locator.Register<IImageFactory>(new ImageFactory("Images"));
        }

        private void SlideHandler(object sender, SlideEventArgs e)
        {
            this._widgets.ForEach(w => w.OnSlide(e));

            Invalidate();
            Update();
        }

        private void MouseUpHandler(object sender, ClickEventArgs e)
        {
            this._widgets.ForEach(w => w.OnMouseUp(e));
        }

        private void MouseDownHandler(object sender, ClickEventArgs e)
        {
            this._widgets.ForEach(w => w.OnMouseDown(e));
        }

        private void MovementHandler(object sender, MovementEventArgs e)
        {
            this._widgets.ForEach(w => w.OnMovement(e));

            Invalidate();
            Update();
        }

        private void ClickHandler(object sender, ClickEventArgs e)
        {
            InvokeOnTarget(e.Location, widget => widget.OnClick(e));
        }

        private void InvokeOnTarget(Point point, Action<Widget> handler)
        {
            for (var i = this._widgets.Count - 1; i >= 0; i--)
            {
                var widget = this._widgets[i];
                if (widget.HitTest(point))
                {
                    handler(widget);
                    break;
                }
            } 
        }

        public void AddWidget(Widget widget)
        {
            this._widgets.Add(widget);
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //base.OnPaintBackground(e);
        }

        private Brush _brush = new SolidBrush(Color.White);

        protected override void OnPaint(PaintEventArgs e)
        {
            var startTick = Environment.TickCount;

            this._backBuffer.Graphics.Clear(Color.White);

            foreach (var widget in this._widgets)
            {
                widget.Draw(this._backBuffer.Graphics);
            }

            e.Graphics.DrawImage(this._backBuffer.Buffer, 0, 0);

            base.OnPaint(e);

            var tickDelta = Environment.TickCount - startTick;

            e.Graphics.DrawString("Paint duration: " + tickDelta + "ms", this.Font, this._brush, 1, this.Bounds.Height - 15);
        }
    }
}